package zfzAI;
import java.awt.Point;

import javax.swing.JOptionPane;

import skeleton.Board;
import skeleton.ChessInfo;
import skeleton.Solution;
import util.ForbiddenChecker;


public class AI extends Thread implements Solution {
	private static CGameMap aiMap,priorityMap;
	private static int myColor;
	private static Point nextStep,last,workinglast;
	private static int[][] way={{-1,0},{-1,-1},{0,-1},{1,-1},{-1,1},{0,1},{1,1},{1,0}};
	private static Thread aiInst;
	private static boolean ThreadStop=false;
	private static int level;
	private static int[][][][][] depth;
	private static boolean canStop=false;
	private static ForbiddenChecker fchecker = new ForbiddenChecker();
	public AI()
	{
		this.level=1;
		aiMap=new CGameMap();
		priorityMap=new CGameMap();
		myColor=0;
		nextStep=new Point(-1,-1);
		last=new Point();
		depth=new int[aiMap.width][][][][];
		for(int p1=0;p1<aiMap.width;++p1)
		{
			depth[p1]=new int[aiMap.height][][][];
			for(int p2=0;p2<aiMap.height;++p2)
			{
				depth[p1][p2]=new int[2][][];
				for(int p3=0;p3<2;++p3)
				{
					depth[p1][p2][p3]=new int[8][];
					for(int p4=0;p4<8;++p4)
						{
							depth[p1][p2][p3][p4]=new int[5];
							for(int p5=0;p5<5;++p5)
								depth[p1][p2][p3][p4][p5]=0;
						}
				}
				
			}
		}
	}
	public void run()
	{
		aiInst=Thread.currentThread();
		int x,y;
		while(true)
		{
			canStop=false;
			
			canStop=true;
			try {
				Thread.sleep(100);
				while(ThreadStop)
					Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			//System.out.println(String.valueOf(last.x*100+last.y));
		}
		
	}
	private void deamonDepth()
	{
		int x,y;
		workinglast=new Point(last.x,last.y);
		int color=aiMap.getP(last.x, last.y);
		if(color>=0)
		for(int p=0;p<8;++p)
			for(int step=1;step<5;++step)
			{
				x=workinglast.x+way[p][0]*step;
				y=workinglast.y+way[p][1]*step;
				if(aiMap.getP(x, y)!=-1) continue;
				for(int i=step;i<5;++i)
				{
					if(depth[x][y][1-color][7-p][i-1]>0) depth[x][y][color][7-p][i]=0;
					else depth[x][y][color][7-p][i]+=1;
					depth[x][y][1-color][7-p][i]=0;
				}
			}
	}
	public void work(int x,int y)
	{
		priorityMap.setP(x,y,getPriority(x,y));
	}
	public int getPriority(int x,int y)
	{
		int temp1,temp2,p1,p2,priority=0;
		Point t=new Point(x,y);
		for(int i=0;i<4;++i)
		{
			temp1=spreadLen(t,way[i][0],way[i][1],myColor);
			temp2=spreadLen(t,-way[i][0],-way[i][1],myColor);
			if(aiMap.getP(x+way[i][0]*(temp1+1),y+way[i][1]*(temp1+1))==-1)
				temp1+=1;
			if(aiMap.getP(x-way[i][0]*(temp2+1),y-way[i][1]*(temp2+1))==-1)
				temp2+=1;
			priority+=temp1+temp2;
			if(temp1+temp2>=5)
				priority+=(temp1+temp2)*20;
			for(int o=0;o<5;++o)
			{
				temp1=depth[x][y][myColor][i][o]+depth[x][y][myColor][7-i][4-o];
				if(temp1>=2) 
					if(aiMap.getP(x+way[i][0]*(o+1),y+way[i][1]*(o+1))==1-myColor)
						if(aiMap.getP(x+way[7-i][0]*(5-o),y+way[7-i][1]*(5-o))==1-myColor)
							priority+=temp1;
						else
							priority+=temp1*3;
					else
						if(aiMap.getP(x+way[7-i][0]*(5-o),y+way[7-i][1]*(5-o))==1-myColor)
							priority+=temp1*3;
						else priority+=temp1*15;
						   
			}
		}
		for(int i=0;i<4;++i)
		{
			temp1=spreadLen(t,way[i][0],way[i][1],1-myColor);
			temp2=spreadLen(t,-way[i][0],-way[i][1],1-myColor);
			if(aiMap.getP(x+way[i][0]*(temp1+1),y+way[i][1]*(temp1+1))==-1)
				p1=1;
			else p1=0;
			if(aiMap.getP(x-way[i][0]*(temp2+1),y-way[i][1]*(temp2+1))==-1)
				p2=1;
			else p2=0;
			priority+=(temp1+temp2);
			if(temp1+temp2==1)
				priority+=2;
			else if(temp1+temp2==2)
				priority+=10*(p1+p2);
			else if(temp1+temp2==3)
				priority+=50*(p1+p2);
			else if(temp1+temp2>=4)
				priority+=(temp1+temp2)*50;
			
			for(int o=0;o<5;++o)
			{
				temp1=depth[x][y][1-myColor][i][o]+depth[x][y][1-myColor][7-i][4-o];
				if(temp1>=2&&o-depth[x][y][1-myColor][i][o]<2
						&&4-o-depth[x][y][1-myColor][7-i][4-o]<2) 
					if(aiMap.getP(x+way[i][0]*(o+1),y+way[i][1]*(o+1))==myColor)
						if(aiMap.getP(x+way[7-i][0]*(5-o),y+way[7-i][1]*(5-o))==myColor)
							priority+=temp1;
						else
							priority+=temp1*3;
					else
						if(aiMap.getP(x+way[7-i][0]*(5-o),y+way[7-i][1]*(5-o))==myColor)
							priority+=temp1*3;
						else priority+=temp1*15;
				if(temp1==4)
					priority+=400;
			}
		}
		
		return priority;
	}
	
	public  void set(int color,int x,int y)
	{
		aiMap.setP(x, y, color);
		last.x=x;
		last.y=y;
		deamonDepth();
		int xx,yy;
		for(int i=0;i<8;++i)
			for(int q=1;q<5;++q)
				{
					xx=last.x+way[i][0]*q;yy=last.y+way[i][1]*q;
					if(aiMap.getP(xx, yy)==-1)
						priorityMap.setP(xx,yy,getPriority(xx,yy));
				}
	}
	public  Point getNextStep() 
	{
		ThreadStop=true;
		
		Point p=CanIWin(myColor);
		if(p.x!=-1){ThreadStop=false; return p;}
		p=CanIWin(1-myColor);
		if(p.x!=-1) {ThreadStop=false; return p;}
		p=get4Line(myColor);
		if(p.x!=-1 && fchecker.forbiddenCheck(aiMap.getBoard(), p.x, p.y)
				==ForbiddenChecker.NO_FORBIDDEN) {ThreadStop=false; return p;}
		//p=get4Line(1-myColor);
		//if(p.x!=-1) {ThreadStop=false; return p;}
		
		
		
		ThreadStop=false;
		return largePriority();
		
		//aiInst.notifyAll();
	
	}
	private Point largePriority()
	{
		int l=-2,x=0,y=0;
		for(int i=0;i<aiMap.width;++i)
			for(int o=0;o<aiMap.height;++o)
				if(aiMap.getP(i, o)==-1 && priorityMap.getP(i, o)>l 
						&& fchecker.forbiddenCheck(aiMap.getBoard(), i, o)
								==ForbiddenChecker.NO_FORBIDDEN)
				{
					x=i;y=o;l=priorityMap.getP(i, o);
				}
		return new Point(x,y);
	}
	private int spreadLen(Point source,int wayx,int wayy,int color)
	{
		int x=source.x+wayx,y=source.y+wayy;
		int len=0;
		while(aiMap.getP(x,y)==color)
		{
			x+=wayx;
			y+=wayy;
			++len;
		}
		return len;
	}
	private Point CanIWin(int color)
	{
		int temp1,temp2;
		for(int i=0;i<aiMap.width;++i)
			for(int o=0;o<aiMap.height;++o)
				if(aiMap.getP(i,o)==-1)
					for(int p=0;p<8;++p)
						
					{
						temp1=spreadLen(new Point(i,o), way[p][0],way[p][1], color);
						temp2=spreadLen(new Point(i,o),way[7-p][0],way[7-p][1],color);
						if(temp1+temp2>=4)
							return new Point(i,o);
					}
		return new Point(-1,-1);
	}
	private Point get4Line(int color)
	{
		for(int i=0;i<aiMap.width;++i)
		for(int o=0;o<aiMap.height;++o)
			if(aiMap.getP(i, o)==color)
				for(int p=0;p<8;++p)
				{
					int len=1+spreadLen(new Point(i,o),way[p][0],way[p][1],color);
					if(len>2 && aiMap.getP(i+way[p][0]*len, o+way[p][1]*len)==-1
							&& aiMap.getP(i+way[p][0]*(len+1), o+way[p][1]*(len+1))==-1)
						return new Point(i+way[p][0]*len,o+way[p][1]*len);
				}
		return new Point(-1,-1);
	}
	public int get2(int x,int y)
	{
		return priorityMap.getP(x, y);
	}
	private Point getCross33()
	{return null;}
	private Point balanceMap()
	{return null;}
	@Override
	public int solve(Board board, ChessInfo info) {
		try {
			sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if (info.row == 100) {
			info.row = 7; info.col = 7;
			set(0, 7, 7);
			return -1;
		}
		System.out.println("op put : " + info.row + " " + info.col);
		set(1, info.row, info.col);
		Point t = getNextStep();
		info.row = (byte) t.x;
		info.col = (byte) t.y;
		set(0, info.row, info.col);
		aiMap.showMap();
		System.out.println("my choice : " + t.x + " " + t.y);
		return -1;
	}
}
